#include "ByteImage.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

ByteImage::ByteImage(int width, int height) : Image(width, height) {
	imageBufferR = unique_ptr<Byte[]>(new Byte[width * height]());
	imageBufferG = unique_ptr<Byte[]>(new Byte[width * height]());
	imageBufferB = unique_ptr<Byte[]>(new Byte[width * height]());
}

ByteImage::ByteImage(string filename) : Image(0, 0) {
	int comp = 0;
	stbi_uc * data = stbi_load(filename.c_str(), &this->width, &this->height, &comp, STBI_rgb);
	imageBufferR = unique_ptr<Byte[]>(new Byte[width * height]());
	imageBufferG = unique_ptr<Byte[]>(new Byte[width * height]());
	imageBufferB = unique_ptr<Byte[]>(new Byte[width * height]());
	for (int x = 0; x < width; x++)
		for (int y = 0; y < height; y++) {
			int p = y * width + x;
			imageBufferR[p] = data[3 * p];
			imageBufferG[p] = data[3 * p + 1];
			imageBufferB[p] = data[3 * p + 2];
		}
	delete[] data;
}

void ByteImage::setColor(int x, int y, const Color &color) {
	int p = y * width + x;
	color.gammaCorrect_inv(oneOverGamma).toByte(imageBufferR[p], imageBufferG[p], imageBufferB[p]);
}

void ByteImage::addColor(int x, int y, const Color &color) {
	Byte r, g, b;
	color.gammaCorrect_inv(oneOverGamma).toByte(r, g, b);
	int p = y * width + x;
	imageBufferR[p] = CLAMPX(imageBufferR[p] + r, 0, 255);
	imageBufferG[p] = CLAMPX(imageBufferG[p] + g, 0, 255);
	imageBufferB[p] = CLAMPX(imageBufferB[p] + b, 0, 255);
}

void ByteImage::clearColor(int x, int y) {
	int p = y * width + x;
	imageBufferR[p] = 0;
	imageBufferG[p] = 0;
	imageBufferB[p] = 0;
}

Color ByteImage::getColor(int x, int y) const {
	int p = y * width + x;
	return ColorByte(imageBufferR[p], imageBufferG[p], imageBufferB[p]);
}

void ByteImage::getColor(Color & color, int x, int y) const {
	int p = y * width + x;
	color.r = imageBufferR[p];
	color.g = imageBufferG[p];
	color.b = imageBufferB[p];
	color /= 255.0;
}

Color ByteImage::getOutputColor(int x, int y) const {
	return getColor(x, y);
}

void ByteImage::getOutputColor(Color & color, int x, int y) const {
	getColor(color, x, y);
}

int ByteImage::getColor_int(int x, int y) const {
	int p = y * width + x;
	return RGB2Int(imageBufferR[p], imageBufferG[p], imageBufferB[p]);
}

int ByteImage::getOutputColor_int(int x, int y) const {
	return getColor_int(x, y);
}
